home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / iface.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  12KB  |  528 lines

  1. /* @(#) $Header: iface.c,v 1.11 92/05/14 13:20:06 deyke Exp $ */
  2.  
  3. /* IP interface control and configuration routines
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "proc.h"
  11. #include "iface.h"
  12. #include "ip.h"
  13. #include "netuser.h"
  14. #include "ax25.h"
  15. #include "enet.h"
  16. #include "pktdrvr.h"
  17. #include "cmdparse.h"
  18. #include "commands.h"
  19.  
  20. static void showiface __ARGS((struct iface *ifp));
  21. static int mask2width __ARGS((int32 mask));
  22. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  23. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  24. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  25. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  26. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  27. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  28. static int ifforw __ARGS((int argc,char *argv[],void *p));
  29. static int ifencap __ARGS((int argc,char *argv[],void *p));
  30. static int ifcrc __ARGS((int argc,char *argv[],void *p));
  31.  
  32. /* Interface list header */
  33. struct iface *Ifaces = &Loopback;
  34.  
  35. /* Loopback pseudo-interface */
  36. struct iface Loopback = {
  37.     &Encap,         /* Link to next entry */
  38.     "loopback",     /* name         */
  39.     0x7f000001L,    /* addr         127.0.0.1 */
  40.     0xffffffffL,    /* broadcast    255.255.255.255 */
  41.     0xffffffffL,    /* netmask      255.255.255.255 */
  42.     MAXINT16,       /* mtu          No limit */
  43.     0,              /* flags        */
  44.     0,              /* trace        */
  45.     NULLCHAR,       /* trfile       */
  46.     NULLFILE,       /* trfp         */
  47.     NULLIF,         /* forw         */
  48.     NULL,           /* rxproc       */
  49.     NULL,           /* txproc       */
  50.     NULL,           /* supv         */
  51.     0,              /* dev          */
  52.     NULL,           /* (*ioctl)     */
  53.     NULLFP,         /* (*iostatus)  */
  54.     NULLFP,         /* (*stop)      */
  55.     NULLCHAR,       /* hwaddr       */
  56.     NULL,           /* extension    */
  57.     CL_NONE,        /* type         */
  58.     0,              /* xdev         */
  59.     &Iftypes[0],    /* iftype       */
  60.     NULLFP,         /* (*send)      */
  61.     NULLFP,         /* (*output)    */
  62.     NULLFP,         /* (*raw)       */
  63.     NULLVFP,        /* (*status)    */
  64.     NULLFP,         /* (*discard)   */
  65.     NULLFP,         /* (*echo)      */
  66.     0,              /* ipsndcnt     */
  67.     0,              /* rawsndcnt    */
  68.     0,              /* iprecvcnt    */
  69.     0,              /* rawrcvcnt    */
  70.     0,              /* lastsent     */
  71.     0,              /* lastrecv     */
  72.     0,              /* sendcrc      */
  73.     0,              /* crcerrors    */
  74.     0,              /* ax25errors   */
  75. };
  76. /* Encapsulation pseudo-interface */
  77. struct iface Encap = {
  78.     NULLIF,
  79.     "encap",        /* name         */
  80.     INADDR_ANY,     /* addr         0.0.0.0 */
  81.     0xffffffffL,    /* broadcast    255.255.255.255 */
  82.     0xffffffffL,    /* netmask      255.255.255.255 */
  83.     MAXINT16,       /* mtu          No limit */
  84.     0,              /* flags        */
  85.     0,              /* trace        */
  86.     NULLCHAR,       /* trfile       */
  87.     NULLFILE,       /* trfp         */
  88.     NULLIF,         /* forw         */
  89.     NULL,           /* rxproc       */
  90.     NULL,           /* txproc       */
  91.     NULL,           /* supv         */
  92.     0,              /* dev          */
  93.     NULL,           /* (*ioctl)     */
  94.     NULLFP,         /* (*iostatus)  */
  95.     NULLFP,         /* (*stop)      */
  96.     NULLCHAR,       /* hwaddr       */
  97.     NULL,           /* extension    */
  98.     CL_NONE,        /* type         */
  99.     0,              /* xdev         */
  100.     &Iftypes[0],    /* iftype       */
  101.     ip_encap,       /* (*send)      */
  102.     NULLFP,         /* (*output)    */
  103.     NULLFP,         /* (*raw)       */
  104.     NULLVFP,        /* (*status)    */
  105.     NULLFP,         /* (*discard)   */
  106.     NULLFP,         /* (*echo)      */
  107.     0,              /* ipsndcnt     */
  108.     0,              /* rawsndcnt    */
  109.     0,              /* iprecvcnt    */
  110.     0,              /* rawrcvcnt    */
  111.     0,              /* lastsent     */
  112.     0,              /* lastrecv     */
  113.     0,              /* sendcrc      */
  114.     0,              /* crcerrors    */
  115.     0,              /* ax25errors   */
  116. };
  117.  
  118. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  119.  
  120. struct cmds Ifcmds[] = {
  121.     "broadcast",            ifbroad,        0,      2,      NULLCHAR,
  122.     "crc",                  ifcrc,          0,      2,      NULLCHAR,
  123.     "encapsulation",        ifencap,        0,      2,      NULLCHAR,
  124.     "forward",              ifforw,         0,      2,      NULLCHAR,
  125.     "ipaddress",            ifipaddr,       0,      2,      NULLCHAR,
  126.     "linkaddress",          iflinkadr,      0,      2,      NULLCHAR,
  127.     "mtu",                  ifmtu,          0,      2,      NULLCHAR,
  128.     "netmask",              ifnetmsk,       0,      2,      NULLCHAR,
  129.     "rxbuf",                ifrxbuf,        0,      2,      NULLCHAR,
  130.     NULLCHAR,
  131. };
  132.  
  133. /* Process packets in the Hopper */
  134. void
  135. network(i,v1,v2)
  136. int i;
  137. void *v1;
  138. void *v2;
  139. {
  140.     struct mbuf *bp;
  141.     struct phdr phdr;
  142.  
  143. loop:
  144.     while(Hopper == NULLBUF)
  145.         pwait(&Hopper);
  146.  
  147.     /* Process the input packet */
  148.     bp = dequeue(&Hopper);
  149.     pullup(&bp,(char *)&phdr,sizeof(phdr));
  150.     if(phdr.iface != NULLIF){
  151.         phdr.iface->rawrecvcnt++;
  152.         phdr.iface->lastrecv = secclock();
  153.     }
  154.     dump(phdr.iface,IF_TRACE_IN,phdr.type,bp);
  155.     switch(phdr.type){
  156. #ifdef  KISS
  157.     case CL_KISS:
  158.         kiss_recv(phdr.iface,bp);
  159.         break;
  160. #endif
  161. #ifdef  AX25
  162.     case CL_AX25:
  163.         ax_recv(phdr.iface,bp);
  164.         break;
  165. #endif
  166. #ifdef  ETHER
  167.     case CL_ETHERNET:
  168.         eproc(phdr.iface,bp);
  169.         break;
  170. #endif
  171. #ifdef ARCNET
  172.     case CL_ARCNET:
  173.         aproc(phdr.iface,bp);
  174.         break;
  175. #endif
  176. #ifdef PPP
  177.     case CL_PPP:
  178.         ppp_proc(phdr.iface,bp);
  179.         break;
  180. #endif
  181.     /* These types have no link layer protocol at the point when they're
  182.      * put in the hopper, so they can be handed directly to IP. The
  183.      * separate types are just for user convenience when running the
  184.      * "iface" command.
  185.      */
  186.     case CL_NONE:
  187.     case CL_SERIAL_LINE:
  188.     case CL_SLFP:
  189.         ip_route(phdr.iface,bp,0);
  190.         break;
  191.     default:
  192.         free_p(bp);
  193.         break;
  194.     }
  195.     /* Let everything else run - this keeps the system from wedging
  196.      * when we're hit by a big burst of packets
  197.      */
  198.     pwait(NULL);
  199.     goto loop;
  200. }
  201.  
  202. /* put mbuf into Hopper for network task
  203.  * returns 0 if OK
  204.  */
  205. int
  206. net_route(ifp, type, bp)
  207. struct iface *ifp;
  208. int type;
  209. struct mbuf *bp;
  210. {
  211.     struct mbuf *nbp;
  212.     struct phdr phdr;
  213.  
  214.     phdr.iface = ifp;
  215.     phdr.type = type;
  216.  
  217.     if ((nbp = pushdown(bp,sizeof(phdr))) == NULLBUF ){
  218.         return -1;
  219.     }
  220.     memcpy( &nbp->data[0],(char *)&phdr,sizeof(phdr));
  221.     enqueue(&Hopper,nbp);
  222.     /* Especially on slow machines, serial I/O can be quite
  223.      * compute intensive, so release the machine before we
  224.      * do the next packet.  This will allow this packet to
  225.      * go on toward its ultimate destination. [Karn]
  226.      */
  227.     pwait(NULL);
  228.     return 0;
  229. }
  230.  
  231. /* Set interface parameters */
  232. int
  233. doifconfig(argc,argv,p)
  234. int argc;
  235. char *argv[];
  236. void *p;
  237. {
  238.     struct iface *ifp;
  239.     int i;
  240.  
  241.     if(argc < 2){
  242.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  243.             showiface(ifp);
  244.         return 0;
  245.     }
  246.     if((ifp = if_lookup(argv[1])) == NULLIF){
  247.         printf("Interface %s unknown\n",argv[1]);
  248.         return 1;
  249.     }
  250.     if(argc == 2){
  251.         showiface(ifp);
  252.         if ( ifp->show != NULLVFP ) {
  253.             (*ifp->show)(ifp);
  254.         }
  255.         return 0;
  256.     }
  257.     if(argc == 3){
  258.         printf("Argument missing\n");
  259.         return 1;
  260.     }
  261.     for(i=2;i<argc-1;i+=2)
  262.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  263.  
  264.     return 0;
  265. }
  266.  
  267. /* Set interface IP address */
  268. static int
  269. ifipaddr(argc,argv,p)
  270. int argc;
  271. char *argv[];
  272. void *p;
  273. {
  274.     struct iface *ifp = p;
  275.  
  276.     ifp->addr = resolve(argv[1]);
  277.     return 0;
  278. }
  279.  
  280. /* Set link (hardware) address */
  281. static int
  282. iflinkadr(argc,argv,p)
  283. int argc;
  284. char *argv[];
  285. void *p;
  286. {
  287.     struct iface *ifp = p;
  288.  
  289.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  290.         printf("Can't set link address\n");
  291.         return 1;
  292.     }
  293.     if(ifp->hwaddr != NULLCHAR)
  294.         free(ifp->hwaddr);
  295.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  296.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  297.     return 0;
  298. }
  299.  
  300. /* Set interface broadcast address. This is actually done
  301.  * by installing a private entry in the routing table.
  302.  */
  303. static int
  304. ifbroad(argc,argv,p)
  305. int argc;
  306. char *argv[];
  307. void *p;
  308. {
  309.     struct iface *ifp = p;
  310.     struct route *rp;
  311.  
  312.     rp = rt_blookup(ifp->broadcast,32);
  313.     if(rp != NULLROUTE && rp->iface == ifp)
  314.         rt_drop(ifp->broadcast,32);
  315.     ifp->broadcast = resolve(argv[1]);
  316.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  317.     return 0;
  318. }
  319.  
  320. /* Set the network mask. This is actually done by installing
  321.  * a routing entry.
  322.  */
  323. static int
  324. ifnetmsk(argc,argv,p)
  325. int argc;
  326. char *argv[];
  327. void *p;
  328. {
  329.     struct iface *ifp = p;
  330.     struct route *rp;
  331.  
  332.     /* Remove old entry if it exists */
  333.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  334.     if(rp != NULLROUTE)
  335.         rt_drop(rp->target,rp->bits);
  336.  
  337.     ifp->netmask = htol(argv[1]);
  338.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  339.     return 0;
  340. }
  341.  
  342. /* Command to set interface encapsulation mode */
  343. static int
  344. ifencap(argc,argv,p)
  345. int argc;
  346. char *argv[];
  347. void *p;
  348. {
  349.     struct iface *ifp = p;
  350.  
  351.     if(setencap(ifp,argv[1]) != 0){
  352.         printf("Encapsulation mode '%s' unknown\n",argv[1]);
  353.         return 1;
  354.     }
  355.     return 0;
  356. }
  357. /* Function to set encapsulation mode */
  358. int
  359. setencap(ifp,mode)
  360. struct iface *ifp;
  361. char *mode;
  362. {
  363.     struct iftype *ift;
  364.  
  365.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  366.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  367.             break;
  368.     if(ift->name == NULLCHAR){
  369.         return -1;
  370.     }
  371.     ifp->iftype = ift;
  372.     ifp->send = ift->send;
  373.     ifp->output = ift->output;
  374.     ifp->type = ift->type;
  375.     return 0;
  376. }
  377. /* Set interface receive buffer size */
  378. static int
  379. ifrxbuf(argc,argv,p)
  380. int argc;
  381. char *argv[];
  382. void *p;
  383. {
  384.     return 0;       /* To be written */
  385. }
  386.  
  387. /* Set interface Maximum Transmission Unit */
  388. static int
  389. ifmtu(argc,argv,p)
  390. int argc;
  391. char *argv[];
  392. void *p;
  393. {
  394.     struct iface *ifp = p;
  395.  
  396.     ifp->mtu = atoi(argv[1]);
  397.     return 0;
  398. }
  399.  
  400. /* Set interface forwarding */
  401. static int
  402. ifforw(argc,argv,p)
  403. int argc;
  404. char *argv[];
  405. void *p;
  406. {
  407.     struct iface *ifp = p;
  408.  
  409.     ifp->forw = if_lookup(argv[1]);
  410.     if(ifp->forw == ifp)
  411.         ifp->forw = NULLIF;
  412.     return 0;
  413. }
  414.  
  415. static int
  416. ifcrc(argc,argv,p)
  417. int argc;
  418. char *argv[];
  419. void *p;
  420. {
  421.     struct iface *ifp = p;
  422.  
  423.     return setbool(&ifp->sendcrc, "CRC generation", argc, argv);
  424. }
  425.  
  426. /* Display the parameters for a specified interface */
  427. static void
  428. showiface(ifp)
  429. register struct iface *ifp;
  430. {
  431.     char tmp[25];
  432.  
  433.     printf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  434.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  435.     if(ifp->iftype == NULLIFT){
  436.         printf("not set\n");
  437.     } else {
  438.         printf("%s\n",ifp->iftype->name);
  439.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  440.             printf("           Link addr %s\n",
  441.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  442.     }
  443.     printf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  444.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  445.     if(ifp->forw != NULLIF)
  446.         printf("           output forward to %s\n",ifp->forw->name);
  447.     printf("           sent: ip %lu tot %lu idle %s\n",
  448.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  449.     printf("           recv: ip %lu tot %lu idle %s\n",
  450.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  451.     printf("           CRC %s errors %lu\n",
  452.      ifp->sendcrc ? "enabled" : "disabled", ifp->crcerrors);
  453.     printf("           bad ax25 headers %lu\n",
  454.      ifp->ax25errors);
  455.     printf("\n");
  456. }
  457.  
  458. /* Given the ascii name of an interface, return a pointer to the structure,
  459.  * or NULLIF if it doesn't exist
  460.  */
  461. struct iface *
  462. if_lookup(name)
  463. char *name;
  464. {
  465.     register struct iface *ifp;
  466.  
  467.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  468.         if(strcmp(ifp->name,name) == 0)
  469.             break;
  470.     return ifp;
  471. }
  472.  
  473. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  474.  * NULLIF otherwise.
  475.  * This is used to tell if an incoming IP datagram is for us, or if it
  476.  * has to be routed.
  477.  */
  478. struct iface *
  479. ismyaddr(addr)
  480. int32 addr;
  481. {
  482.     register struct iface *ifp;
  483.  
  484.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  485.         if(addr == ifp->addr)
  486.             break;
  487.     return ifp;
  488. }
  489.  
  490. /* Given a network mask, return the number of contiguous 1-bits starting
  491.  * from the most significant bit.
  492.  */
  493. static int
  494. mask2width(mask)
  495. int32 mask;
  496. {
  497.     int width,i;
  498.  
  499.     width = 0;
  500.     for(i = 31;i >= 0;i--){
  501.         if(!(mask & (1L << i)))
  502.             break;
  503.         width++;
  504.     }
  505.     return width;
  506. }
  507.  
  508. /* return buffer with name + comment */
  509. char *
  510. if_name(ifp,comment)
  511. struct iface *ifp;
  512. char *comment;
  513. {
  514.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  515.     strcpy( result, ifp->name );
  516.     return strcat( result, comment );
  517. }
  518.  
  519. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  520. int
  521. bitbucket(ifp,bp)
  522. struct iface *ifp;
  523. struct mbuf *bp;
  524. {
  525.     free_p(bp);
  526.     return 0;
  527. }
  528.